<template>
  <div class="main-container">
    <!-- 标题框 -->
    <div class="header-container">
      <div class="header-box">
        <button @click="goBack" class="btn btn-back">返回</button>
        <h1 class="title">多图建模</h1>
      </div>
    </div>

    <!-- 内容框 -->
    <div class="content-container">
      <!-- 内容框，包含功能介绍和视频上传 -->
      <div class="content-box">
        <!-- 功能介绍文字，封装在一个深色、有圆角的框内 -->
        <div class="introduction-box">
          <p class="introduction-text">
            上传一段围绕古青铜器的视频，即可重建其三维模型。
          </p>
          <p class="note-text">
            （注：请确保拍摄时长在15-25秒，尽量避免周围环境的干扰）
          </p>
        </div>

        <!-- 视频上传 -->
        <h3 class="video-title">上传视频</h3>
        <div class="video-box">
          <div class="video-content">
            <video v-if="selectedVideoPreview" :src="selectedVideoPreview" controls class="preview-video"></video>
            <div v-else class="placeholder" @click="selectVideo">
              <p>点击选择视频</p>
            </div>
          </div>
        </div>
        <input type="file" @change="handleFileUpload" ref="fileInput" accept="video/*" style="display: none;" />

        <!-- 上传和重建按钮 -->
        <div class="upload-buttons">
          <button v-if="selectedVideoPreview && !uploading && !processing" @click="uploadVideo" class="btn btn-upload">
            上传并重建
          </button>
          <button v-if="selectedVideoPreview && !uploading && !processing" @click="resetUpload" class="btn btn-reupload">
            重新上传
          </button>
        </div>

        <!-- 提示处理时间 -->
        <div v-if="selectedVideoPreview && !uploading && !processing" class="processing-time-hint">
          <p>处理大约需要30分钟，请耐心等待。</p>
        </div>

        <!-- 上传进度 -->
        <div v-if="uploading" class="uploading-overlay">
          <div class="progress-bar">
            <div class="progress" :style="{ width: uploadProgress + '%' }"></div>
          </div>
          <p class="uploading-text">正在上传... {{ uploadProgress.toFixed(0) }}%</p>
        </div>

        <!-- 处理进度 -->
        <div v-if="processing" class="processing-overlay">
          <div class="progress-bar">
            <div class="progress" :style="{ width: progress + '%' }"></div>
          </div>
          <p class="processing-text">{{ currentStep }} - {{ progress.toFixed(1) }}%</p>
          <button @click="cancelProcessing" class="btn btn-cancel">取消重建</button>
        </div>

        <!-- 处理完成区域 -->
        <div v-if="processingCompleted && modelAvailable" class="result-section">
          <p class="completion-text">处理完成</p>
          <button @click="viewModel" class="btn btn-view-model">查看重建模型</button>
          <button @click="downloadModel" class="btn btn-download-model">下载模型</button>
        </div>

        <!-- 重建工作还在继续 -->
        <div v-if="processingCompleted && !modelAvailable" class="result-section">
          <p class="completion-text">重建工作还在继续，请耐心等待。</p>
        </div>
      </div>

      <!-- 模态框 -->
      <div v-if="modelModalVisible" class="modal" @click="closeModelModal">
        <div class="modal-content" @click.stop>
          <!-- 使用 three.js 展示模型 -->
          <div id="threejs-container"></div>
          <button @click="closeModelModal" class="btn-close">
            关闭
          </button>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import * as THREE from 'three';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import axios from 'axios';
import { BASE_URL } from '@/config.js';
export default {
  data() {
    return {
      selectedFile: null,
      selectedVideoPreview: null,
      uploading: false,
      uploadProgress: 0,
      uploadCompleted: false,
      processing: false,
      progress: 0,
      steps: [
        '正在提取图像帧',
        '正在计算相机位姿',
        '正在NeRF重建',
        '正在模型裁剪',
        '正在转化obj格式'
      ],
      currentStepIndex: 0,
      currentStep: '',
      processingCompleted: false,
      timer: null,
      modelModalVisible: false,
      modelAvailable: false,
      checkModelInterval: null,
      videoId: '',
      userId: null,
      elapsedTime: 0, // 用于记录已经过的时间
    };
  },
  mounted() {
    this.getUserId();
    this.loadState();
  },
  methods: {
    getUserId() {
      const userId = localStorage.getItem('userId');
      if (userId) {
        this.userId = userId;
      } else {
        alert('请先登录！');
        // 可以跳转到登录页面，或者根据需求处理
      }
    },
    loadState() {
      const savedState = localStorage.getItem('reconstructionState');
      if (savedState) {
        const state = JSON.parse(savedState);
        Object.assign(this.$data, state);
        // 如果正在处理，重新启动计时器
        if (this.processing) {
          this.startProcessing(true); // 传递参数表示恢复处理
        }
        if (this.processingCompleted && !this.modelAvailable) {
          this.checkModelAvailability();
        }
      }
    },
    saveState() {
      const state = {
        videoId: this.videoId,
        processing: this.processing,
        progress: this.progress,
        currentStepIndex: this.currentStepIndex,
        currentStep: this.currentStep,
        processingCompleted: this.processingCompleted,
        modelAvailable: this.modelAvailable,
        selectedVideoPreview: this.selectedVideoPreview,
        elapsedTime: this.elapsedTime,
      };
      localStorage.setItem('reconstructionState', JSON.stringify(state));
    },
    selectVideo() {
      this.$refs.fileInput.click();
    },
    handleFileUpload(event) {
      this.selectedFile = event.target.files[0];
      this.createVideoPreview();
    },
    createVideoPreview() {
      if (this.selectedFile) {
        this.selectedVideoPreview = URL.createObjectURL(this.selectedFile);
      }
    },
    uploadVideo() {
      if (!this.selectedFile) return;
      this.uploading = true;
      this.uploadProgress = 0;

      const formData = new FormData();
      formData.append('video', this.selectedFile);
      formData.append('userId', this.userId); // 添加 userId

      axios.post('/api/upload_video', formData, {
        headers: { 'Content-Type': 'multipart/form-data' },
        onUploadProgress: (progressEvent) => {
          this.uploadProgress = (progressEvent.loaded / progressEvent.total) * 100;
        },
      })
        .then((response) => {
          this.uploading = false;
          this.uploadCompleted = true;
          this.videoId = response.data.videoId;
          // 显示视频上传成功
          alert('视频上传成功');
          // 开始处理进度
          this.startProcessing();
          this.saveState();
        })
        .catch((error) => {
          this.uploading = false;
          console.error('视频上传失败:', error);
          alert('视频上传失败，请重试');
        });
    },
    resetUpload() {
      // 清除本地存储的状态
      localStorage.removeItem('reconstructionState');
      this.uploading = false;
      this.uploadProgress = 0;
      this.uploadCompleted = false;
      this.selectedFile = null;
      this.selectedVideoPreview = null;
      this.processing = false;
      this.progress = 0;
      this.currentStepIndex = 0;
      this.currentStep = '';
      this.processingCompleted = false;
      this.modelAvailable = false;
      this.elapsedTime = 0;
      if (this.$refs.fileInput) {
        this.$refs.fileInput.value = null;
      }
      if (this.timer) {
        clearInterval(this.timer);
      }
      if (this.checkModelInterval) {
        clearInterval(this.checkModelInterval);
      }
    },
    goBack() {
      window.history.back();
    },
    startProcessing(resuming = false) {
      this.processing = true;
      const totalDuration = 3600; // 总时间（秒）
      const stepDuration = totalDuration / this.steps.length;
      if (!resuming) {
        this.currentStepIndex = 0;
        this.currentStep = this.steps[this.currentStepIndex];
        this.progress = 0;
        this.elapsedTime = 0;
      }
      const startTime = Date.now() - (this.elapsedTime || 0) * 1000;

      this.timer = setInterval(() => {
        this.elapsedTime = Math.floor((Date.now() - startTime) / 1000);
        this.progress = (this.elapsedTime / totalDuration) * 100;

        if (this.elapsedTime >= (this.currentStepIndex + 1) * stepDuration) {
          this.currentStepIndex++;
          if (this.currentStepIndex < this.steps.length) {
            this.currentStep = this.steps[this.currentStepIndex];
          }
        }

        if (this.elapsedTime >= totalDuration) {
          clearInterval(this.timer);
          this.processingCompleted = true;
          this.processing = false;
          // 检查模型是否可用
          this.checkModelAvailability();
        }
        this.saveState();
      }, 1000); // 每秒更新一次
    },
    checkModelAvailability() {
      this.checkModelInterval = setInterval(() => {
        axios.get(`/api/check_model/${this.videoId}`)
          .then((response) => {
            if (response.data.modelAvailable) {
              this.modelAvailable = true;
              clearInterval(this.checkModelInterval);
            } else {
              this.modelAvailable = false;
            }
            this.saveState();
          })
          .catch((error) => {
            console.error('检查模型可用性失败:', error);
          });
      }, 5000); // 每5秒检查一次
    },
    viewModel() {
      if (!this.modelAvailable) {
        alert('重建工作还在继续，请耐心等待。');
        return;
      }
      this.modelModalVisible = true;
      this.$nextTick(() => {
        this.loadModel();
      });
    },
    closeModelModal() {
      this.modelModalVisible = false;
      // 清理 three.js 场景
      if (this.renderer) {
        this.renderer.dispose();
        this.renderer.forceContextLoss();
        this.renderer.content = null;
        this.renderer.domElement = null;
        this.renderer = null;
      }
    },
    loadModel() {
      const container = document.getElementById('threejs-container');
      // 初始化 three.js 场景
      const scene = new THREE.Scene();
      const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);
      const renderer = new THREE.WebGLRenderer({ antialias: true });
      renderer.setSize(container.clientWidth, container.clientHeight);
      container.innerHTML = '';
      container.appendChild(renderer.domElement);
      this.renderer = renderer;

      // 添加光源
      const light = new THREE.AmbientLight(0xffffff, 1);
      scene.add(light);

      // 加载模型
      const loader = new OBJLoader();
      // 加载模型
      loader.load(`/models/${this.videoId}.obj`, (obj) => {
        scene.add(obj);
        camera.position.z = 5;
        const animate = () => {
          requestAnimationFrame(animate);
          obj.rotation.y += 0.01;
          renderer.render(scene, camera);
        };
        animate();
      }, undefined, (error) => {
        console.error('模型加载失败:', error);
      });
    },
    downloadModel() {
      if (!this.modelAvailable) {
        alert('重建工作还在继续，请耐心等待。');
        return;
      }
      // 下载模型
      const link = document.createElement('a');
      link.href = `/models/${this.videoId}.obj`;
      link.download = '重建模型.obj';
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    },
  },
  beforeDestroy() {
    if (this.timer) {
      clearInterval(this.timer);
    }
    if (this.checkModelInterval) {
      clearInterval(this.checkModelInterval);
    }
  },
  cancelProcessing() {
    if (confirm('确定要取消重建吗？')) {
      // 停止定时器
      if (this.timer) {
        clearInterval(this.timer);
        this.timer = null;
      }
      // 重置状态
      this.processing = false;
      this.progress = 0;
      this.currentStepIndex = 0;
      this.currentStep = '';
      this.processingCompleted = false;
      this.modelAvailable = false;

      // 从 localStorage 中移除数据
      localStorage.removeItem('reconstructionData');
    }
  },
};
</script>

<style scoped>
/* 您的样式代码保持不变 */

/* 整体样式，与您提供的示例文件保持一致 */

@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@700&family=Playfair+Display&display=swap');

.main-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 100vh;
  background-image: url('@/assets/s2.jpg');
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
  background-attachment: fixed;
  margin: 0;
  padding: 0;
}

.header-container {
  margin: 20px auto;
  width: 100%;
}

.header-box {
  margin-top: 52px;
  margin-left: 200px;
  margin-right: 200px;
  display: flex;
  justify-content: center;
  align-items: center;
  background: linear-gradient(135deg, #1c2827, #5e4b3c);
  border-radius: 20px;
  padding: 10px 20px;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.7);
}

.title {
  font-size: 32px;
  font-weight: bold;
  color: #fdf6e3;
  margin: 0 10px;
  font-family: 'Playfair Display', serif;
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
}

.btn-back {
  background-color: #8b4513;
  color: #fdf6e3;
  padding: 10px 20px;
  font-size: 18px;
  border: none;
  border-radius: 20px;
  cursor: pointer;
  transition: background-color 0.3s, transform 0.3s, box-shadow 0.3s;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.5);
}

.btn-back:hover {
  background-color: #5e4b3c;
  transform: translateY(-2px);
  box-shadow: 0 6px 15px rgba(0, 0, 0, 0.7);
}

.content-container {
  width: 800px;
  margin: 0 auto;
}

.content-box {
  padding: 20px;
  background-color: #2e2e2e;
  border-radius: 20px;
  margin-bottom: 20px;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.7);
}

.introduction-box {
  background: #3e2a1f;
  border-radius: 15px;
  padding: 30px;
  margin-bottom: 20px;
  position: relative;
  overflow: hidden;
  animation: fadeIn 1s ease-in-out;
  text-align: center;
}

.introduction-text {
  font-family: 'Playfair Display', serif;
  font-size: 20px;
  color: #fdf6e3;
  line-height: 1.8;
  margin: 0;
  position: relative;
  text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);
  font-weight: 600;
  letter-spacing: 0.5px;
}

.note-text {
  font-family: 'Playfair Display', serif;
  font-size: 16px;
  color: #d4af37;
  line-height: 1.5;
  margin-top: 15px;
  opacity: 0.9;
  text-align: center;
}

.video-title {
  font-size: 18px;
  color: #fdf6e3;
  text-align: center;
  margin-bottom: 10px;
  font-family: 'Montserrat', sans-serif;
  text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.5);
}

.video-box {
  width: 300px;
  height: 300px;
  background-color: #3e2a1f;
  border-radius: 20px;
  position: relative;
  overflow: hidden;
  margin: 0 auto 20px auto;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.7);
}

.video-content {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.preview-video {
  max-width: 100%;
  max-height: 100%;
  border-radius: 10px;
}

.placeholder {
  font-size: 18px;
  color: #d4af37;
  cursor: pointer;
  animation: pulse 2s infinite;
}

.placeholder p {
  margin: 0;
}

.upload-buttons {
  display: flex;
  justify-content: center;
  gap: 10px;
}

.btn-upload {
  background-color: #d4af37;
  color: #2e2e2e;
  padding: 12px 24px;
  font-size: 18px;
  border: none;
  border-radius: 30px;
  cursor: pointer;
  transition: background-color 0.3s, transform 0.3s, box-shadow 0.3s;
  box-shadow: 0 4px 14px rgba(212, 175, 55, 0.4);
}

.btn-upload:hover {
  background-color: #b89c34;
  transform: translateY(-3px);
  box-shadow: 0 6px 16px rgba(212, 175, 55, 0.6);
}

.btn-reupload {
  background-color: #5e4b3c;
  color: #fdf6e3;
  padding: 12px 24px;
  font-size: 18px;
  border: none;
  border-radius: 30px;
  cursor: pointer;
  transition: background-color 0.3s, transform 0.3s, box-shadow 0.3s;
  box-shadow: 0 4px 14px rgba(94, 75, 60, 0.4);
}

.btn-reupload:hover {
  background-color: #3e2a1f;
  transform: translateY(-3px);
  box-shadow: 0 6px 16px rgba(94, 75, 60, 0.6);
}

.processing-time-hint {
  text-align: center;
  margin-top: 10px;
}

.processing-time-hint p {
  color: #d4af37;
  font-size: 16px;
}

.uploading-overlay,
.processing-overlay {
  position: relative;
  text-align: center;
  margin-top: 20px;
}

.progress-bar {
  width: 80%;
  height: 10px;
  background-color: #d4af37;
  border-radius: 5px;
  margin: 0 auto 10px auto;
  overflow: hidden;
}

.progress {
  height: 100%;
  background-color: #8b4513;
  width: 0%;
  transition: width 0.5s linear;
}

.uploading-text,
.processing-text {
  font-size: 18px;
  color: #fdf6e3;
  font-family: 'Montserrat', sans-serif;
}

.result-section {
  text-align: center;
  margin-top: 20px;
}

.completion-text {
  font-size: 20px;
  color: #d4af37;
  margin-bottom: 10px;
}

.btn-view-model,
.btn-download-model {
  background-color: #d4af37;
  color: #2e2e2e;
  padding: 12px 24px;
  font-size: 18px;
  border: none;
  border-radius: 30px;
  cursor: pointer;
  margin: 5px;
  transition: background-color 0.3s, transform 0.3s, box-shadow 0.3s;
}

.btn-view-model:hover,
.btn-download-model:hover {
  background-color: #b89c34;
  transform: translateY(-3px);
}

.modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.9);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal-content {
  position: relative;
  width: 80%;
  height: 80%;
  background-color: #2e2e2e;
  border-radius: 10px;
  padding: 20px;
}

#threejs-container {
  width: 100%;
  height: 100%;
}

.btn-close {
  position: absolute;
  top: 10px;
  right: 10px;
  background-color: rgba(212, 175, 55, 0.8);
  border: none;
  border-radius: 50%;
  width: 40px;
  height: 40px;
  cursor: pointer;
  transition: background-color 0.3s, transform 0.3s;
}

.btn-close:hover {
  background-color: rgba(212, 175, 55, 1);
  transform: rotate(90deg);
}

.btn-cancel {
  background-color: #dc3545;
  color: #ffffff;
  padding: 10px 20px;
  font-size: 16px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  margin-top: 10px;
  transition: background-color 0.3s, transform 0.2s;
}

.btn-cancel:hover {
  background-color: #c82333;
  transform: translateY(-2px);
}

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes pulse {
  0% { opacity: 0.6; }
  50% { opacity: 1; }
  100% { opacity: 0.6; }
}
</style>